
#include "mpi.h"
#include <cassert>
#include <iostream>
using namespace std;

int main(int argc, char **argv) {
  int my_rank, num_proc;
  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
  MPI_Comm_size(MPI_COMM_WORLD, &num_proc);
  if (num_proc != 2)
    exit(EXIT_FAILURE);

  MPI_Win bwin, awin;
  int a[2], b[3], c[4];
  if (my_rank == 0) {

    MPI_Win_create(b, sizeof(int) * 3, sizeof(int), MPI_INFO_NULL,
                   MPI_COMM_WORLD, &bwin);
    MPI_Win_create(MPI_BOTTOM, 0, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &awin);
  } else {
    a[0] = 1;
    a[1] = 2;
    b[0] = 10;
    b[1] = 20;
    b[2] = 30;
    c[0] = 101;
    c[1] = 201;
    c[2] = 300;
    c[3] = 400;
    MPI_Win_create(MPI_BOTTOM, 0, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &bwin);
    // 注意与 put 中的disp的区别
    MPI_Win_create(a, sizeof(int) * 2, sizeof(int), MPI_INFO_NULL,
                   MPI_COMM_WORLD, &awin);
  }

  MPI_Win_fence(0, awin);
  if (my_rank == 0) {
    MPI_Get(a, 2, MPI_INT, 1, 0, 2, MPI_INT, awin);
  }
  MPI_Win_fence(0, awin);

  MPI_Win_fence(0, bwin);
  if (my_rank == 1) {
    //  tar
    MPI_Put(c, 3, MPI_INT, 0, 0, 3, MPI_INT, bwin);
  }
  MPI_Win_fence(0, bwin);

  if (my_rank == 0) {
    cout << "myrank =" << my_rank << endl;
    cout << a[0] << "  " << a[1] << endl;
    cout << b[0] << "  " << b[1] << "  " << b[2] << endl;
  } else {
    cout << "myrank =" << my_rank << endl;
    cout << c[0] << "  " << c[1] << "  " << c[2] << endl;
  }

  MPI_Win_fence(0, bwin);
  if (my_rank == 1) {
    //  tar
    MPI_Accumulate(b, 3, MPI_INT, 0, 0, 3, MPI_INT, MPI_SUM, bwin);
  }
  MPI_Win_fence(0, bwin);

  if (my_rank == 0) {
    cout << "myrank =" << my_rank << endl;
    cout << a[0] << "  " << a[1] << endl;
    cout << b[0] << "  " << b[1] << "  " << b[2] << endl;
  } else {
    cout << "myrank =" << my_rank << endl;
    cout << c[0] << "  " << c[1] << "  " << c[2] << endl;
  }

  MPI_Finalize();
  return 0;
}
